﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace RPG_Helper
{
    /// <summary>
    /// Logique d'interaction pour MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        Personnage personnage;

        public MainWindow()
        {
            Dictionary<enumerations.Jeu, Jeu> baseJeu = new Dictionary<enumerations.Jeu, Jeu>();
            #region Ajout dans la base
            baseJeu.Add(enumerations.Jeu.Diablo_II,
                        new Jeu("Diablo II")
                        {
                            JeuCorrespondant = enumerations.Jeu.Diablo_II,
                            ElementsNaturePresent = new List<enumerations.ElementNature>() 
                            { enumerations.ElementNature.Feu, enumerations.ElementNature.Glace, enumerations.ElementNature.Electricite, enumerations.ElementNature.Poison },
                            caracteristiquesPresentes = new List<enumerations.caracteristique>()
                            { enumerations.caracteristique.Force, enumerations.caracteristique.Dexterite, enumerations.caracteristique.Defense,
                              enumerations.caracteristique.Vitalite, enumerations.caracteristique.Energie }
                        });
            baseJeu.Add(enumerations.Jeu.Torchligth,
                        new Jeu("Torchligth")
                        {
                            JeuCorrespondant = enumerations.Jeu.Torchligth,
                            ElementsNaturePresent = new List<enumerations.ElementNature>()
                            { enumerations.ElementNature.Feu, enumerations.ElementNature.Glace, enumerations.ElementNature.Electricite, enumerations.ElementNature.Poison },
                             caracteristiquesPresentes = new List<enumerations.caracteristique>()
                            { enumerations.caracteristique.Force, enumerations.caracteristique.Dexterite, enumerations.caracteristique.Defense, enumerations.caracteristique.Magie }
                        });
            baseJeu.Add(enumerations.Jeu.Autre,
                        new Jeu("Autre")
                        {
                            JeuCorrespondant = enumerations.Jeu.Autre,
                            ElementsNaturePresent = new List<enumerations.ElementNature>(),
                            caracteristiquesPresentes = new List<enumerations.caracteristique>()
                        });
            #endregion

            /*
            Demarrage winPreparations = new Demarrage();
            winPreparations.ShowDialog();
            personnage = new Personnage(winPreparations.Nom, baseJeu[winPreparations.JeuSelectionne]);
             //*/
            personnage = new Personnage("Iris", baseJeu[enumerations.Jeu.Diablo_II]);
            Equipement epee = new Equipement("Super épée de la mort"); epee.ajoutModifications(1, 5, enumerations.ApplicationModification.Directe, enumerations.caracteristique.Force);
            Equipement armure = new Equipement("Armure de plate"); armure.ajoutModifications(1, 100, enumerations.ApplicationModification.Pourcentage, enumerations.caracteristique.Defense);
            Equipement heaume = new Equipement("Heaume de vie"); heaume.ajoutModifications(1, 50, enumerations.ApplicationModification.Pourcentage, enumerations.caracteristique.Vie);
            personnage.addEquipement(epee); personnage.addEquipement(armure); personnage.addEquipement(heaume);

            InitializeComponent();
            this.vieBox.Text = personnage.Vie.ToString();
            this.manaBox.Text = personnage.Mana.ToString();
        }

        #region StackPanel des caractéristiques
        private void caracPanel_Initialized(object sender, EventArgs e)
        {
            foreach(enumerations.caracteristique carac in personnage.caracteristiques)
                this.caracPanel.Children.Add( ligneNouvelElement(carac, Brushes.Black.Color));
        }
        private void caracDispo_Initialized(object sender, EventArgs e)
        {
            if(personnage.JeuDefini) // Si le jeu est prédéfini dans la base, on peut supprimer cette combobox
            { this.caracPanel.Children.Remove(this.caracDispo); return; }

            List<string> scaracs = Enum.GetNames(typeof(enumerations.caracteristique)).ToList<string>();
            scaracs.Remove(Enum.GetName(typeof(enumerations.caracteristique), enumerations.caracteristique.None));
            foreach(enumerations.caracteristique carac in personnage.caracteristiques) // Pour toutes les caractéristiques que le personnage à déjà
                scaracs.Remove(Enum.GetName(typeof(enumerations.caracteristique), carac));

            foreach(string carac in scaracs)
                this.caracDispo.Items.Add(carac);
            if(this.caracDispo.Items.Count == 0) // Si pas d'éléments parce que tous utilisée, on retire
                this.caracPanel.Children.Remove(this.caracDispo); 
        }
        
        private void caracDispo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.caracDispo.SelectedItem == null) return; // Si pas d'élément sélectionné

            string scaracChoisie = (string)this.caracDispo.SelectedItem;
            // Ne peut échouer : la liste ne contient que des chaines directement issues de Enum.GetNames
            enumerations.caracteristique caracChoisie = (enumerations.caracteristique)Enum.Parse(typeof(enumerations.caracteristique), scaracChoisie, true);
            if(this.personnage.addNouvellecaract(caracChoisie)) // Si la caractéristique n'a pas déjà été ajouté
            {
                StackPanel nouvellecarac = ligneNouvelElement(caracChoisie, Brushes.Black.Color);
                this.caracPanel.Children.Insert(this.caracPanel.Children.Count-1, nouvellecarac);
                this.caracDispo.Items.Remove(this.caracDispo.SelectedItem);
                if(this.caracDispo.Items.Count == 0)
                    this.caracPanel.Children.Remove(this.caracDispo); // Si pas d'élément, on retire la liste

            } // Sinon rien
        }

        private void metAJourValeurscaracteristiques()
        {
            personnage.MetAJourStat();
            this.textNom.Text = this.personnage.Nom + "(" + this.personnage.Vie + "," + this.personnage.Mana + ")";
            foreach(UIElement element in this.caracPanel.Children)
            {
                if(element.GetType() == typeof(StackPanel)) // Si on a à faire a une des lignes qui nous intéresse
                {
                    StackPanel sp = (StackPanel)element;
                    enumerations.caracteristique caracLigne = (enumerations.caracteristique)Enum.Parse(typeof(enumerations.caracteristique), ((TextBlock)sp.Children[0]).Text);
                    ((TextBlock)sp.Children[1]).Text = personnage.pointsDe(caracLigne).ToString();
                }
            }
        }

        void bAjVal_Click(object sender, RoutedEventArgs e)
        {
            Button bAjVal = (Button)sender;
            enumerations.caracteristique caracteristiqueConcernee = (enumerations.caracteristique)Enum.Parse(typeof(enumerations.caracteristique), bAjVal.Name);
            personnage.addPointscaract(caracteristiqueConcernee);
            this.metAJourValeurscaracteristiques();
        }
        #endregion

        #region StackPanel des Elements naturels
        private void elementPanel_Initialized(object sender, EventArgs e)
        {
            foreach(enumerations.ElementNature elem in personnage.ElementsNature)
            {
                StackPanel sp = new StackPanel()
                { Orientation = System.Windows.Controls.Orientation.Vertical, Margin = new Thickness(2), Width = this.elementPanel.Width/personnage.ElementsNature.Count};
                Brush couleurElem = new SolidColorBrush(enumerations.ColorElement.couleurElement[elem]);
                TextBlock tb = new TextBlock() { Text = "Dégats : ", Foreground =  couleurElem};
                sp.Children.Add(tb);
                sp.Children.Add(ligneNouvelElement(elem, enumerations.ColorElement.couleurElement[elem],  true));
                tb = new TextBlock() { Text = "Resistance : ", Foreground =  couleurElem };
                sp.Children.Add(tb);
                sp.Children.Add(ligneNouvelElement(elem, enumerations.ColorElement.couleurElement[elem],  false));
                this.elementPanel.Children.Add(sp);
            }
        }
        private void elementDispo_Initialized(object sender, EventArgs e)
        {
            if(this.personnage.JeuDefini) // Si le jeu est défini par une base, on peut supprimer la combobox
            { this.elementPanel.Children.Remove(this.elementDispoPanelContainer); return; }
            
            List<string> sElems = Enum.GetNames(typeof(enumerations.ElementNature)).ToList<string>();
            sElems.Remove(Enum.GetName(typeof(enumerations.ElementNature), enumerations.ElementNature.None));

            foreach(enumerations.ElementNature elem in personnage.ElementsNature) // Pour toutes les caractéristiques que le personnage à déjà
                sElems.Remove(Enum.GetName(typeof(enumerations.ElementNature), elem));

            foreach(string elem in sElems)
                this.elementDispo.Items.Add(elem);
            if(this.elementDispo.Items.Count == 0) // Si pas d'éléments parce que tous utilisée, on retire
                this.elementPanel.Children.Remove(this.elementDispoPanelContainer); 
        }

        private void elementDispo_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.elementDispo.SelectedItem == null) return;

            string sElemChoisi = this.elementDispo.SelectedItem.ToString();
            enumerations.ElementNature elemChoisi = (enumerations.ElementNature)Enum.Parse(typeof(enumerations.ElementNature), sElemChoisi, true);
            if(this.personnage.addNouvelElement(elemChoisi)) 
            {
                StackPanel sp = new StackPanel() 
                { 
                    Orientation = System.Windows.Controls.Orientation.Vertical,
                    Margin = new Thickness(2),
                };


                Brush couleurElem = new SolidColorBrush(enumerations.ColorElement.couleurElement[elemChoisi]);

                TextBlock tb = new TextBlock() { Text = "Dégats : ", Foreground = couleurElem};
                sp.Children.Add(tb);
                sp.Children.Add(ligneNouvelElement(elemChoisi, enumerations.ColorElement.couleurElement[elemChoisi],  true));
                tb = new TextBlock() { Text = "Resistance : ", Foreground = couleurElem };
                sp.Children.Add(tb);
                sp.Children.Add(ligneNouvelElement(elemChoisi, enumerations.ColorElement.couleurElement[elemChoisi],  false));
                this.elementPanel.Children.Add(sp);

                this.elementDispo.Items.Remove(this.elementDispo.SelectedItem);
                if(this.elementDispo.Items.Count == 0)
                    this.elementPanel.Children.Remove(this.elementDispoPanelContainer); // Si pas d'élément, on retire la liste

            } // Sinon rien
        }
        #endregion

        #region StackPanel des Equipements
        private void metAJourEquipements()
        {
            this.equipementPanel.Children.RemoveRange(0, this.equipementPanel.Children.Count-1); // Ne pas supprimer le dernier bouton
            foreach(Equipement eq in personnage.Equipements)
            {
                StackPanel sp = new StackPanel() { Orientation = Orientation.Horizontal, Width = this.equipementPanel.Width };
                Button nomEquip =  new Button() { Content = eq.Nom, FontStyle = (eq.EstActif ? FontStyles.Normal : FontStyles.Italic), Width=200 };
                Button activation = new Button() { Name = eq.Nom.Replace(' ', '_') };
                if(eq.EstActif)
                { activation.Content = "Desactiver"; activation.Click += new RoutedEventHandler(desactiver_Click); }
                else
                { activation.Content = "Activer"; activation.Click += new RoutedEventHandler(activer_Click); }
                Button retirer = new Button() { Name = eq.Nom.Replace(' ', '_'), Content = "Suppr" }; retirer.Click += new RoutedEventHandler(retirer_Click);
                sp.Children.Add(nomEquip);
                sp.Children.Add(activation);
                sp.Children.Add(retirer);
                this.equipementPanel.Children.Insert(this.equipementPanel.Children.Count-1, sp);
            }
        }
        private void equipementPanel_Initialized(object sender, EventArgs e)
        {
            foreach(Equipement eq in personnage.Equipements)
            {
                StackPanel sp = new StackPanel() { Orientation = Orientation.Horizontal, Width = this.equipementPanel.Width };
                Button nomEquip =  new Button() { Content = eq.Nom, FontStyle = (eq.EstActif ? FontStyles.Normal : FontStyles.Italic), Width=200 };
                Button desactiver = new Button() { Content = "Desactiver", Name = eq.Nom.Replace(' ', '_')}; desactiver.Click += new RoutedEventHandler(desactiver_Click);
                Button retirer = new Button() { Name = eq.Nom.Replace(' ', '_'), Content = "Suppr" }; retirer.Click += new RoutedEventHandler(retirer_Click);
                sp.Children.Add(nomEquip);
                sp.Children.Add(desactiver);
                sp.Children.Add(retirer);
                this.equipementPanel.Children.Insert(this.equipementPanel.Children.Count-1, sp);
                metAJourValeurscaracteristiques();
            }
        }
        private void addEquipement_Click(object sender, RoutedEventArgs e)
        {
            AddEquipement winEquip = new AddEquipement(this.personnage.caracteristiques);
            winEquip.ShowDialog();
            personnage.addEquipement(winEquip.EquipementCree);
            StackPanel sp = new StackPanel() { Orientation = Orientation.Horizontal, Width = this.equipementPanel.Width };
            Button nomEquip =  new Button() { Content = winEquip.EquipementCree.Nom, FontStyle = (winEquip.EquipementCree.EstActif ? FontStyles.Normal : FontStyles.Italic), Width=200 };
            Button desactiver = new Button() { Name = winEquip.EquipementCree.Nom.Replace(' ', '_'), Content = "Desactiver" }; desactiver.Click += new RoutedEventHandler(desactiver_Click);
            Button retirer = new Button() { Name = winEquip.EquipementCree.Nom.Replace(' ', '_'), Content = "Suppr" }; retirer.Click += new RoutedEventHandler(retirer_Click);
            sp.Children.Add(nomEquip);
            sp.Children.Add(desactiver);
            sp.Children.Add(retirer);
            this.equipementPanel.Children.Insert(this.equipementPanel.Children.Count-1, sp);
            metAJourValeurscaracteristiques();
        }

        void retirer_Click(object sender, RoutedEventArgs e)
        {
            Button b = (Button)sender;
            foreach(Equipement eq in this.personnage.Equipements)
                if(eq.Nom.Replace(' ', '_') == b.Name.ToString())
                { this.personnage.retirerEquipement(eq); break; }
            this.metAJourEquipements(); 
            this.metAJourValeurscaracteristiques(); 
            return;
        }


        void desactiver_Click(object sender, RoutedEventArgs e)
        {
            for(int i = 0 ; i < this.personnage.Equipements.Count ; i++)
                if(this.personnage.Equipements[i].Nom.Replace(' ', '_') == ((Button)sender).Name)
                { this.personnage.Equipements[i].EstActif = false; break; }
            this.metAJourValeurscaracteristiques();
            this.metAJourEquipements();
        }
        void activer_Click(object sender, RoutedEventArgs e)
        {
            for(int i = 0 ; i < this.personnage.Equipements.Count ; i++)
                if(this.personnage.Equipements[i].Nom.Replace(' ', '_') == ((Button)sender).Name)
                { this.personnage.Equipements[i].EstActif = true; break; }
            this.metAJourValeurscaracteristiques();
            this.metAJourEquipements();
        }
        #endregion

        // second argument indique, si le premier est de type élement, que l'on demande les dégats ou la résistance de cet élément
        private StackPanel ligneNouvelElement(Object o, Color couleurObjet, bool degatsDe=false)
        {
            bool estcarac = false;

            // Il faut les définirs, ne peuvent pas rester indéfini
            enumerations.caracteristique carac = enumerations.caracteristique.None;
            enumerations.ElementNature elem = enumerations.ElementNature.None;

            if(o is enumerations.caracteristique)
            { carac = (enumerations.caracteristique)o; estcarac = true; }
            else if(o is enumerations.ElementNature)
                elem = (enumerations.ElementNature)o;
            else
                throw new Exception("Objet non reconnu par ligneNouvelElement");

            StackPanel nouvellecarac = new StackPanel() { Orientation = Orientation.Horizontal, Height = 25 };
            string sObjetChoisi = (estcarac ? Enum.GetName(typeof(enumerations.caracteristique), carac) : Enum.GetName(typeof(enumerations.ElementNature), elem));

            TextBlock tblNouvellecarac = new TextBlock() { Width = 60, Text = sObjetChoisi, Foreground = new SolidColorBrush(couleurObjet) };
            TextBlock tblVal = new TextBlock()
            {
                Width = 20,
                Text = (estcarac ?  personnage.pointsDe(carac) : (degatsDe ? personnage.DegatsDe(elem) : personnage.ResistanceA(elem))).ToString(),
                TextAlignment = TextAlignment.Right,
                Foreground = new SolidColorBrush(couleurObjet)
            };
            // On met le nom de la caractéristique au bouton pour pouvoir le gérer dans la fonction évennement bAjVal_Click
            Button bAjVal = new Button() { Content = "+", Name = sObjetChoisi, Margin = new Thickness(3) };
            bAjVal.Click += new RoutedEventHandler(bAjVal_Click);

            nouvellecarac.Children.Add(tblNouvellecarac);
            nouvellecarac.Children.Add(tblVal);
            if(estcarac)
                nouvellecarac.Children.Add(bAjVal);

            return nouvellecarac;
        }

        private void textNom_Initialized(object sender, EventArgs e)
        { this.textNom.Text = this.personnage.Nom + "(" + this.personnage.Vie + "," + this.personnage.Mana + ")"; }

        private void vieBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            int nouvelleVie;
            if(Int32.TryParse(this.vieBox.Text, out nouvelleVie))
                this.personnage.Vie = nouvelleVie;
            else
                this.vieBox.Text = "##% ??";
            this.metAJourValeurscaracteristiques();
        }
        private void manaBox_TextChanged(object sender, TextChangedEventArgs e)
        {
            int nouveauMana;
            if(Int32.TryParse(this.manaBox.Text, out nouveauMana))
                this.personnage.Mana = nouveauMana;
            else
                this.manaBox.Text = "##% ??";
            this.metAJourValeurscaracteristiques();
        }



    }
}
